package cn.chiship.sdk.third.service;

import cn.chiship.sdk.cache.service.RedisService;
import cn.chiship.sdk.core.base.BaseResult;
import cn.chiship.sdk.core.base.constants.BaseConstants;
import cn.chiship.sdk.core.exception.ExceptionUtil;
import cn.chiship.sdk.core.exception.custom.BusinessException;
import cn.chiship.sdk.core.util.StringUtil;
import cn.chiship.sdk.core.util.http.HttpUtil;
import cn.chiship.sdk.third.core.common.ThirdConstants;
import cn.chiship.sdk.third.core.model.WeiXinWorkConfigModel;
import cn.chiship.sdk.third.properties.ChishipWxWorkProperties;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.ObjectUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

/**
 * 企业相关业务实现
 * URL:<a href="https://developer.work.weixin.qq.com/document">开发文档</a>
 *
 * @author lijian
 */
@Component
public class WxWorkService {
    protected static final Logger LOGGER = LoggerFactory.getLogger(WxWorkService.class);
    public static final String API_WEI_XIN_SERVER_HOST = "https://qyapi.weixin.qq.com/";
    private static final String ACCESS_TOKEN = "access_token";


    @Resource
    ChishipWxWorkProperties chishipWxWorkProperties;
    @Resource
    RedisService redisService;

    private WeiXinWorkConfigModel weiXinWorkConfigModel;

    private String accessToken = null;

    public WxWorkService config() {
        this.weiXinWorkConfigModel = new WeiXinWorkConfigModel(
                chishipWxWorkProperties.getCorpId(),
                chishipWxWorkProperties.getAppKey(),
                chishipWxWorkProperties.getAppSecret()
        );
        return this;
    }

    public WxWorkService config(WeiXinWorkConfigModel weiXinWorkConfigModel) {
        if (ObjectUtils.isEmpty(weiXinWorkConfigModel)) {
            LOGGER.info("企业微信实例配置为空，将自动加载默认配置信息");
            return config();
        }
        this.weiXinWorkConfigModel = weiXinWorkConfigModel;
        return this;
    }

    public WxWorkService token() {
        BaseResult baseResult = getToken();
        if (!baseResult.isSuccess()) {
            throw new BusinessException(baseResult.getData() + "-" + baseResult.getMessage());
        }
        this.accessToken = baseResult.getData().toString();
        return this;
    }

    /**
     * 获取接口调用凭据
     * URL:<a href="https://developer.work.weixin.qq.com/document/path/91039">文档</a>
     *
     * @return BaseResult
     */
    private BaseResult getToken() {

        try {
            String getTokenUrl = API_WEI_XIN_SERVER_HOST + "cgi-bin/gettoken";
            String key = ThirdConstants.REDIS_WEIXIN_WORK_ACCESS_TOKEN + ":" + this.weiXinWorkConfigModel.getCorpId() + ":" + this.weiXinWorkConfigModel.getAppKey();
            String token = StringUtil.getString(redisService.get(key), null);
            if (!StringUtil.isNullOrEmpty(token)) {
                return BaseResult.ok(token);
            }
            Map<String, Object> query = new HashMap<>(7);
            query.put("corpid", this.weiXinWorkConfigModel.getCorpId());
            query.put("corpsecret", this.weiXinWorkConfigModel.getAppSecret());
            BaseResult baseResult = HttpUtil.getInstance().doGet(getTokenUrl, query);
            baseResult = analysisHttpResponse(baseResult);
            if (!baseResult.isSuccess()) {
                return baseResult;
            }
            JSONObject dataJson = (JSONObject) baseResult.getData();
            token = dataJson.getString(ACCESS_TOKEN);
            long expiresIn = Long.parseLong(dataJson.getString("expires_in"));
            baseResult.setData(token);
            // 提前5分钟过期
            redisService.set(key, token, expiresIn - 5 * 60);
            return baseResult;
        } catch (Exception e) {
            return ExceptionUtil.formatException(e);
        }
    }

    /**
     * 构造网页授权链接 网页授权第一步
     * <a href="https://developer.work.weixin.qq.com/document/path/91022">链接</a>
     *
     * @param params
     * @return 结果
     */
    public String getOauth2Auth(String params) {
        try {
            String redirectUri = chishipWxWorkProperties.getServerDomain() + "/redirectUri/" + weiXinWorkConfigModel.getAppKey();
            LOGGER.info("redirectUri:{}", redirectUri);
            String authorizeUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=CORPID&state=STATE&redirect_uri=REDIRECT_URI&response_type=code&scope=snsapi_privateinfo&agentid=AGENTID#wechat_redirect";
            String url = authorizeUrl
                    .replace("CORPID", weiXinWorkConfigModel.getCorpId())
                    .replace("AGENTID", weiXinWorkConfigModel.getAppKey())
                    .replace("REDIRECT_URI", URLEncoder.encode(redirectUri, BaseConstants.UTF8));
            if (StringUtil.isNullOrEmpty(params)) {
                params = "";
            }
            url = url.replace("STATE", params);
            return url;
        } catch (Exception e) {
            throw new BusinessException("构造网页授权链接发生错误:" + e.getLocalizedMessage());
        }
    }

    /**
     * 构造企业微信登录链接 网页授权第一步
     * <a href="https://open.dingtalk.com/document/orgapp/obtain-identity-credentials">链接</a>
     *
     * @param params
     * @return 结果
     */
    public String getWxLoginSso(String params) {
        try {
            String redirectUri = chishipWxWorkProperties.getServerDomain() + "/redirectUri/" + weiXinWorkConfigModel.getAppKey();
            LOGGER.info("redirectUri:{}", redirectUri);
            String authorizeUrl = "https://login.work.weixin.qq.com/wwlogin/sso/login?login_type=CorpApp&agentid=AGENTID&appid=CORPID&redirect_uri=REDIRECT_URI&state=STATE";
            String url = authorizeUrl
                    .replace("CORPID", weiXinWorkConfigModel.getCorpId())
                    .replace("AGENTID", weiXinWorkConfigModel.getAppKey())
                    .replace("REDIRECT_URI", URLEncoder.encode(redirectUri, BaseConstants.UTF8));
            if (StringUtil.isNullOrEmpty(params)) {
                params = "";
            }
            url = url.replace("STATE", params);
            return url;
        } catch (Exception e) {
            throw new BusinessException("构造企业微信登录链接发生错误:" + e.getLocalizedMessage());
        }
    }

    /**
     * 通过授权码获取登录用户Id 网页授权第二步
     * <a href="https://developer.work.weixin.qq.com/document/path/98177">链接</a>
     *
     * @param code 通过成员授权获取到的code
     * @return 结果
     */
    public BaseResult getUserIdByAuthCode(String code) {

        try {
            String url = API_WEI_XIN_SERVER_HOST + "cgi-bin/auth/getuserinfo";
            Map<String, Object> query = new HashMap<>(7);
            query.put(ACCESS_TOKEN, getAccessToken());
            query.put("code", code);
            BaseResult baseResult = HttpUtil.getInstance().doGet(url, query);
            baseResult = analysisHttpResponse(baseResult);
            if (!baseResult.isSuccess()) {
                return baseResult;
            }
            JSONObject dataJson = (JSONObject) baseResult.getData();
            baseResult.setData(dataJson.getString("userid"));
            return baseResult;
        } catch (Exception e) {
            return ExceptionUtil.formatException(e);
        }
    }

    /**
     * 通过授权码获取登录用户Id 网页授权第二步
     * <a href="https://developer.work.weixin.qq.com/document/path/98177">链接</a>
     *
     * @param code 通过成员授权获取到的code
     * @return 结果
     */
    public BaseResult getUserByAuthCode(String code) {
        try {
            BaseResult baseResult = getUserIdByAuthCode(code);
            if (!baseResult.isSuccess()) {
                return baseResult;
            }
            return getUserByUserId(baseResult.getData().toString());
        } catch (Exception e) {
            return ExceptionUtil.formatException(e);
        }
    }

    /**
     * 根据UserId获取详情
     * <a href="https://developer.work.weixin.qq.com/document/path/96255">链接</a>
     *
     * @param userId 成员UserID
     * @return 结果
     */
    public BaseResult getUserByUserId(String userId) {

        try {
            String url = API_WEI_XIN_SERVER_HOST + "cgi-bin/user/get";
            Map<String, Object> query = new HashMap<>(7);
            query.put(ACCESS_TOKEN, getAccessToken());
            query.put("userid", userId);
            BaseResult baseResult = HttpUtil.getInstance().doGet(url, query);
            return analysisHttpResponse(baseResult);
        } catch (Exception e) {
            return ExceptionUtil.formatException(e);
        }
    }


    /**
     * userid  openid互换
     * <a href="https://developer.work.weixin.qq.com/document/path/96261">链接</a>
     *
     * @param value        UserId/OpenId
     * @param isUserToOpen 是否是user转open
     * @return 结果
     */
    public BaseResult exchangeOpenIdAndUserId(String value, Boolean isUserToOpen) {

        try {
            String subUrl = "convert_to_openid";
            String valueLabel = "userid";
            if (Boolean.FALSE.equals(isUserToOpen)) {
                subUrl = "convert_to_userid";
                valueLabel = "openid";
            }
            String url = API_WEI_XIN_SERVER_HOST + "cgi-bin/user/" + subUrl;
            Map<String, Object> query = new HashMap<>(7);
            query.put(ACCESS_TOKEN, getAccessToken());
            Map<String, Object> body = new HashMap<>(7);
            body.put(valueLabel, value);
            BaseResult baseResult = HttpUtil.getInstance().doPost(url, query, body);
            baseResult = analysisHttpResponse(baseResult);
            if (!baseResult.isSuccess()) {
                return baseResult;
            }
            JSONObject dataJson = (JSONObject) baseResult.getData();
            baseResult.setData(Boolean.TRUE.equals(isUserToOpen) ? dataJson.getString("openid") : dataJson.getString("userid"));
            return baseResult;
        } catch (Exception e) {
            return ExceptionUtil.formatException(e);
        }
    }

    public String getAccessToken() {
        if (StringUtil.isNullOrEmpty(accessToken)) {
            throw new BusinessException("token为空！请链式调用如下方法：config().token()获得Token");
        }
        return accessToken;
    }

    public WeiXinWorkConfigModel getWeiXinWorkConfigModel() {
        return weiXinWorkConfigModel;
    }

    private BaseResult analysisHttpResponse(BaseResult baseResult) {
        Integer successStatus = 0;
        String errCode = "errcode";
        String errMsg = "errmsg";
        if (!baseResult.isSuccess()) {
            return baseResult;
        }
        JSONObject json = JSON.parseObject(StringUtil.getString(baseResult.getData()));
        if (json.containsKey(errCode)) {
            if (successStatus.equals(json.getInteger(errCode))) {
                return BaseResult.ok(json);
            } else {
                return BaseResult.error("【" + json.getInteger(errCode) + "】：" + json.getString(errMsg));
            }
        } else {
            return BaseResult.ok(json);
        }

    }
}
